<!-- templates/applicant/interview-room.html -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>AI面试官</title>
    <script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@3.18.0/dist/tf.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/face-api.js@0.22.2/dist/face-api.min.js"></script>

    <style>
        #preview {
            width: 250px; /* 增加预览宽度 */
            position: fixed;
            top: 20px;
            right: 20px;
            border: 2px solid #007bff;
            border-radius: 4px;
            box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); /* 添加阴影 */
        }
        .warning-counter {
            position: fixed;
            top: 20px;
            left: 20px;
            background: #ffc107;
            padding: 10px;
            border-radius: 4px;
            font-size: 18px; /* 增加字体大小 */
            font-weight: bold; /* 加粗字体 */
        }

        body {
            font-family: Arial, sans-serif;
            margin: 20px;
            background-color: #f4f4f9;
            color: #333;
        }
        .container {
            max-width: 800px;
            margin: 0 auto;
            padding: 20px;
            background-color: #fff;
            border-radius: 8px;
            box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
        }
        .conversation {
            margin-bottom: 20px;
            max-height: 400px;
            overflow-y: auto;
            border: 1px solid #ccc;
            padding: 10px;
            border-radius: 4px;
            background-color: #f9f9f9;
        }
        .user, .assistant {
            margin: 5px 0;
        }
        .user {
            color: #007bff;
        }
        .assistant {
            color: #28a745;
        }
        .evaluation {
            margin-top: 20px;
            padding: 10px;
            border: 1px solid #ccc;
            border-radius: 4px;
            background-color: #f9f9f9;
        }
        .input-container {
            display: flex;
            justify-content: space-between;
            align-items: flex-end;
        }
        textarea {
            width: 75%; /* 增加输入框宽度 */
            padding: 10px;
            border: 1px solid #ccc;
            border-radius: 4px;
            resize: none;
            height: 100px;
        }
        button {
            padding: 10px 20px;
            background-color: #007bff;
            color: #fff;
            border: none;
            border-radius: 4px;
            cursor: pointer;
            font-size: 16px; /* 增加按钮字体大小 */
        }
        button:hover {
            background-color: #0056b3;
        }
    </style>
</head>
<body>
    <div class="container">
        <h1>AI面试官</h1>
        <div class="warning-counter">警告次数：<span id="warningCount">0</span>/10</div>
        <div id="conversation" class="conversation"></div>
        <div class="input-container">
            <textarea id="userInput" placeholder="请输入你的回答"></textarea>
            <button onclick="sendUserInput()">发送</button>
        </div>
        <div id="evaluation" class="evaluation"></div>
    </div>
    <video id="preview" autoplay muted playsinline></video>
    <canvas id="canvas" style="display: none;"></canvas>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.0.1/socket.io.js"></script>
    <script>
    // 防作弊相关变量
    let mediaStream = null;
    let warningCount = 0;
    let isInterviewEnded = false;
    let faceDetectionInterval;
    let modelLoaded = false;
    let lastValidDetection = null; // 新增：用于跟踪有效检测

    // Socket.io 初始化
    const socket = io();

    // 初始化人脸检测模型
    async function loadModels() {
        await faceapi.nets.tinyFaceDetector.loadFromUri('/static/models');
        await faceapi.nets.faceLandmark68Net.loadFromUri('/static/models');
        modelLoaded = true;
    }

   // 初始化媒体设备（增加镜像处理）
    async function initializeMedia() {
        try {
            mediaStream = await navigator.mediaDevices.getUserMedia({
                video: {
                    width: 800,
                    height: 600,
                    facingMode: 'user'  // 强制使用前置摄像头
                },
                audio: true
            });

            const videoElement = document.getElementById('preview');
            videoElement.srcObject = mediaStream;
            videoElement.style.transform = 'scaleX(-1)'; // 添加镜像翻转

            await new Promise(resolve => setTimeout(resolve, 3000));
            return true;
        } catch (error) {
            alert('必须启用摄像头和麦克风才能进行面试！');
            window.location.href = '/dashboard';
            return false;
        }
    }
    // 新增校准状态变量
    let calibrationPassed = false;
    let calibrationInterval;

    // 在startInterview函数中添加校准环节
    async function startInterview(resumeId, jobId) {
        const mediaGranted = await initializeMedia();
        if (!mediaGranted) return;

        await loadModels();

        // ------------------ 新增校准环节 ------------------
        try {
            await calibrationCheck();
            calibrationPassed = true;
        } catch (error) {
            alert('校准失败：' + error.message);
            endInterview('设备校准未通过，请检查摄像头后重试');
            return;
        }
        // ------------------------------------------------

        faceDetectionInterval = setInterval(detectFace, 3000);
        alert('请确保全程正面面对摄像头！累计10次警告将自动终止面试！');
        socket.emit('start_interview', {
            resume_id: resumeId,
            job_id: jobId,
            warning_count: warningCount
        });
    }

    // 校准检查函数（包含可视化提示）
    async function calibrationCheck() {
        const video = document.getElementById('preview');
        const canvas = document.getElementById('canvas');
        const calibrationInfo = document.createElement('div');

        // 创建校准提示界面
        calibrationInfo.id = 'calibration-info';
        calibrationInfo.style = `
            position: fixed;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            background: rgba(0,0,0,0.8);
            color: white;
            padding: 20px;
            border-radius: 10px;
            text-align: center;
            z-index: 1000;
        `;
        document.body.appendChild(calibrationInfo);

        return new Promise((resolve, reject) => {
            let validFrames = 0;
            let timeout = 30; // 校准超时30秒

            // 更新提示信息
            const updateMessage = (text) => {
                calibrationInfo.innerHTML = `
                    <h3>设备校准中 (${timeout--}秒)</h3>
                    <p>${text}</p>
                    <div style="width:200px;height:20px;background:#333;margin:10px auto">
                        <div style="width:${validFrames*20}%;height:100%;background:#4CAF50;"></div>
                    </div>
                `;
            };

            // 校准检测定时器
            const checkInterval = setInterval(async () => {
                if (timeout <= 0) {
                    clearInterval(checkInterval);
                    document.body.removeChild(calibrationInfo);
                    reject(new Error('校准超时'));
                }

                const detection = await faceapi.detectSingleFace(
                    video,
                    new faceapi.TinyFaceDetectorOptions()
                ).withFaceLandmarks();

                if (detection) {
                    // 绘制面部框帮助用户调整位置
                    const ctx = canvas.getContext('2d');
                    ctx.clearRect(0, 0, canvas.width, canvas.height);
                    faceapi.draw.drawDetections(canvas, [detection]);

                    // 检查面部位置是否合适
                    const box = detection.detection.box;
                    const isCentered = Math.abs(box.x + box.width/2 - video.videoWidth/2) < 50;
                    const isProperSize = box.width > 150 && box.width < 300;

                    if (isCentered && isProperSize) {
                        validFrames++;
                        updateMessage('请保持当前姿势...');
                    } else {
                        validFrames = Math.max(0, validFrames-1);
                        const tips = [];
                        if (!isCentered) tips.push('请将面部对准画面中心');
                        if (!isProperSize) tips.push('请调整与摄像头的距离');
                        updateMessage(tips.join('<br>'));
                    }
                } else {
                    validFrames = Math.max(0, validFrames-2);
                    updateMessage('未检测到面部，请正对摄像头');
                }

                // 通过条件
                if (validFrames >= 5) {
                    clearInterval(checkInterval);
                    ctx.clearRect(0, 0, canvas.width, canvas.height);
                    document.body.removeChild(calibrationInfo);
                    resolve();
                }
            }, 500);

            // 超时定时器
            const timeoutInterval = setInterval(() => {
                if (timeout <= 0) {
                    clearInterval(timeoutInterval);
                }
            }, 1000);
        });
    }

    async function detectFace() {
        if (!calibrationPassed || !modelLoaded || isInterviewEnded) return;

<!--    // 视线检测逻辑-->
<!--    async function detectFace() {-->
<!--        if (!modelLoaded || isInterviewEnded) return;-->

        const video = document.getElementById('preview');
        const canvas = document.getElementById('canvas');
        const displaySize = {
            width: video.videoWidth,
            height: video.videoHeight
        };
        faceapi.matchDimensions(canvas, displaySize);

        const detection = await faceapi.detectSingleFace(
            video,
            new faceapi.TinyFaceDetectorOptions()
        ).withFaceLandmarks();

        // 使用镜像坐标转换函数
        const mirrorX = (x) => video.videoWidth - x;

        if (detection) {
            // 更新最后有效检测时间
            lastValidDetection = Date.now();

            // 转换坐标到镜像视图
            const mirroredBox = {
                x: mirrorX(detection.detection.box.x + detection.detection.box.width),
                y: detection.detection.box.y,
                width: detection.detection.box.width,
                height: detection.detection.box.height
            };

            // 计算面部中心（镜像坐标）
            const faceCenterX = mirroredBox.x - mirroredBox.width/2;

            // 计算眼睛中心（镜像坐标）
            const landmarks = detection.landmarks;
            const leftEye = landmarks.getLeftEye().map(p => ({ x: mirrorX(p.x), y: p.y }));
            const rightEye = landmarks.getRightEye().map(p => ({ x: mirrorX(p.x), y: p.y }));

            const eyeCenterX = (leftEye[0].x + rightEye[3].x) / 2;

            // 改进的检测逻辑：加入垂直方向检测
            const xOffset = Math.abs(eyeCenterX - faceCenterX);
            const yOffset = Math.abs(leftEye[0].y - rightEye[3].y);

            // 动态调整阈值（基于面部大小）
            const widthThreshold = mirroredBox.width * 0.25;
            const heightThreshold = mirroredBox.height * 0.15;

            // 多条件判断（需同时满足水平和垂直偏移）
            if (xOffset > widthThreshold && yOffset < heightThreshold) {
                handleCheating('检测到异常视线方向！');
            }
        } else {
            // 10秒内未检测到人脸视为作弊
            if (Date.now() - lastValidDetection > 10000) {
                handleCheating('长时间未检测到人脸！');
            }
        }
    }

    // 作弊处理（增加频率限制）
    function handleCheating(reason) {
        // 10秒内不重复警告同一原因
        if (this.lastWarning &&
            Date.now() - this.lastWarning < 10000 &&
            this.lastReason === reason) return;

        warningCount++;
        this.lastWarning = Date.now();
        this.lastReason = reason;

        document.getElementById('warningCount').textContent = warningCount;
        socket.emit('cheating_warning', { reason, count: warningCount });

        if (warningCount >= 10) {
            endInterview('作弊次数超过限制，面试已终止！');
        }
    }

    // 结束面试并跳转
    function endInterview(reason) {
        isInterviewEnded = true;

        // 清理资源
        if (mediaStream) {
            mediaStream.getTracks().forEach(track => track.stop());
        }
        clearInterval(faceDetectionInterval);

        // 禁用交互
        document.getElementById('userInput').disabled = true;
        document.querySelector('button').disabled = true;

        // 提示并跳转
        alert(reason);
        window.location.href = '/dashboard';  // 跳转到仪表盘

        // 通知服务器
        socket.emit('interview_terminated', {
            reason: reason,
            warning_count: warningCount
        });
    }

    // 切屏检测
    document.addEventListener('visibilitychange', () => {
        if (document.visibilityState === 'hidden' && !isInterviewEnded) {
            handleCheating('检测到切换屏幕！');
        }
    });

    // 启动面试
    async function startInterview(resumeId, jobId) {
        const mediaGranted = await initializeMedia();
        if (!mediaGranted) return;

        await loadModels();
        faceDetectionInterval = setInterval(detectFace, 3000);

        alert('请确保全程正面面对摄像头！累计10次警告将自动终止面试！');
        socket.emit('start_interview', {
            resume_id: resumeId,
            job_id: jobId,  // 修正变量名大小写
            warning_count: warningCount
        });
    }

    // Socket事件监听
    socket.on('connect', () => {
        console.log('Connected to server');
        startInterview('3', '1');  // 初始化面试
    });

    socket.on('new_message', (data) => {
        displayMessage(data.role, data.content);
    });

    socket.on('evaluation_report', (data) => {
        displayEvaluation(data.report);
    });

    socket.on('force_terminate', (data) => {
        endInterview(data.reason);
    });

    // 界面更新函数
    function displayMessage(role, content) {
        const conversationDiv = document.getElementById('conversation');
        const messageElement = document.createElement('div');
        messageElement.className = role;
        messageElement.textContent = `${role}: ${content}`;
        conversationDiv.appendChild(messageElement);
        conversationDiv.scrollTop = conversationDiv.scrollHeight;
    }

    function displayEvaluation(evaluationReport) {
        const evaluationDiv = document.getElementById('evaluation');
        evaluationDiv.innerHTML = `<pre>${evaluationReport}</pre>`;
    }

    // 用户输入处理
    function sendUserInput() {
        const userInput = document.getElementById('userInput').value;
        if (userInput.trim() === '') {
            alert('请输入你的回答');
            return;
        }
        displayMessage('user', userInput);
        socket.emit('user_input', { content: userInput });
        document.getElementById('userInput').value = '';
    }
</script>
<!-- 视频元素添加镜像样式 -->
<video id="preview1" autoplay muted playsinline style="transform: scaleX(-1);"></video>
</body>
</html>
